[POJ1149]pigs

2019-07-15
POJ

题意

有$n$个猪圈,有$m$个顾客会依次前来购买至多$M_i$只猪

每次顾客会打开$k$个猪圈,只有猪圈被打开的之后,被关上之前可以任意调换,最大化卖猪的数量

题解

每次顾客来卖猪的时候视为先把所有的指定猪圈里的猪寄存到顾客手上

之后再去那些猪圈买猪的时候直接从顾客手里买

调试记录

bfs的时候只扩展e[i].f>0的边

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <cstdio>
#include <queue>
#include <cstring>
const int INF = 0x3f3f3f3f;
const int maxn = 3005;
using namespace std;
struct E{
int to, nxt, f;
}e[maxn << 1];
int head[maxn], tot = -1;
void addedge(int u, int v, int f){
e[++tot].to = v, e[tot].nxt = head[u], e[tot].f = f;
head[u] = tot;
}
void ins(int u, int v, int f){
addedge(u, v, f); addedge(v, u, 0);
}
int n, m, keep[maxn], dep[maxn];
bool bfs(){
queue <int> q; q.push(0);
memset(dep, 0, sizeof dep); dep[0] = 1;
while (!q.empty()){
int cur = q.front(); q.pop();
for (int i = head[cur]; i != -1; i = e[i].nxt)
if (!dep[e[i].to] && e[i].f){
dep[e[i].to] = dep[cur] + 1;
q.push(e[i].to);
}
}
return dep[n + m + 1];
}
int dfs(int cur, int Max){
if (cur == n + m + 1) return Max;
for (int i = head[cur]; i != -1; i = e[i].nxt){
if (dep[e[i].to] == dep[cur] + 1 && e[i].f){
if (int flow = dfs(e[i].to, min(Max - flow, e[i].f))){
e[i].f -= flow;
e[i ^ 1].f += flow;
return flow;
}
}
}
return 0;
}
int maxflow = 0;
void Dinic(){
while (bfs()){
while (int tmp = dfs(0, INF)) maxflow += tmp;
}
}
int main(){
memset(head, -1, sizeof head);
scanf("%d%d", &n, &m);
for (int f, i = 1; i <= n; i++){
scanf("%d", &f);
ins(0, i, f);
}
for (int i = 1; i <= m; i++){
int k, M; scanf("%d", &k);
for (int a, j = 1; j <= k; j++){
scanf("%d", &a);
if (keep[a] == 0) ins(a, i + n, INF);
else ins(keep[a], i + n, INF);
keep[a] = i + n;
} scanf("%d", &M);
ins(i + n, n + m + 1, M);
}
Dinic();
printf("%d\n", maxflow);
return 0;
}